Go Back Game of Life Screenshot

Conway's Game of Life – Cellular Automaton

Role: Solo Developer | Designer | Programmer

Engine: Unity

Platform: PC (Web)

Project On: GitHub

1. Introduction

Conway’s Game of Life – Cellular Automaton is a Unity-based interactive simulation that visualizes the emergent behavior of cellular automata as defined by mathematician John Conway.

This project was developed to explore simulation design, optimization techniques, and procedural content generation in Unity. By implementing the Game of Life ruleset using object pooling, dynamic grid generation, and real-time UI feedback, the project demonstrates proficiency in system architecture, performance management, and visual data representation.

2. Concept and Objectives

The Game of Life is a zero-player game that evolves based on an initial state and a set of deterministic rules. Each cell in a grid can be alive or dead, and its fate in the next generation depends on the number of living neighbors it has.

The objective of this Unity project was to create a scalable, efficient, and visually intuitive version of this simulation that runs smoothly at high resolutions while remaining interactive and informative.

Key Project Goals:

  • Accurate Rule Implementation: Faithfully apply Conway’s four rules to determine cell survival, death, or reproduction.
  • Optimized Rendering: Use an object pooling system to manage thousands of cell objects efficiently.
  • Dynamic Visualization: Represent live and dead cells through real-time sprite rendering.
  • User Interaction: Include basic input (restart, play/pause) and on-screen information such as generation count and population.
  • Readable, Modular Code: Create clean, extensible scripts suitable for future experiments in cellular automata.

The emphasis was on clarity and scalability — creating a foundation for future extensions like alternate automaton rules, color-coding systems, or user-drawn initial states.

3. Development Process

3.1 System Overview

The simulation is composed of three primary components:

  • Cell.cs Defines individual cell behavior and appearance.
  • GameOfLife.cs Manages grid initialization, rule updates, pooling, and simulation state.
  • GameUI.cs (Prototype) Handles UI and user control logic for start, pause, and reset.

This modular design ensures a clear separation between visualization, simulation logic, and user interface.

3.2 Grid Initialization

At startup, the program initializes a two-dimensional array of cells (Cell[,] grid) with configurable width and height.

Each grid position has a random 30% chance of starting as alive. Live cells are obtained from a pre-allocated pool rather than dynamically instantiated — a key optimization decision for performance.

The camera is automatically positioned and scaled to ensure the entire grid remains visible regardless of dimensions:

                    
                        Camera.main.transform.position = new Vector3(0, 0, -10);
                        Camera.main.orthographicSize = (height * cellSize) / 2f;
                    
                

This ensures visual consistency even when the grid resolution is changed.

3.3 Conway’s Rules Implementation

The core algorithm runs at a fixed time interval (0.1 seconds) via InvokeRepeating.

Each update performs the following sequence:

  1. Neighbor Counting:

    For each cell, the program counts its eight surrounding neighbors using a doubleloop over the offset range (-1, 1).

  2. Rule Evaluation:

    The simulation applies Conway’s rules:

    • Any live cell with 2 or 3 neighbors survives.
    • Any dead cell with exactly 3 neighbors becomes alive.
    • All other cells die or remain dead.
  3. State Transition:

    The new generation is stored in a secondary 2D array (nextGen) beforeapplying the updates to the grid.

This approach ensures synchronous updates, maintaining correct simulation behavior.

3.4 Object Pooling System

With potentially over 20,000 cells on screen, naïve object creation and destruction each frame would quickly degrade performance.

To solve this, the project uses a custom object pooling system implemented via a Queue:

  • At startup, poolSize (e.g., 5000) inactive cells are pre-instantiated.
  • When a cell becomes alive, it’s dequeued and positioned.
  • When a cell dies, it’s deactivated and enqueued back to the pool.
                    
                        Cell GetCellFromPool(int x, int y) {
                            Cell cell = cellPool.Dequeue();
                            cell.transform.position = position;
                            cell.gameObject.SetActive(true);
                            return cell;
                        }                        
                    
                

This drastically reduces garbage collection spikes and ensures smooth frame rates — a key factor when rendering large-scale automata.

3.5 Visualization and Feedback

The Cell class handles only visual state:

                    
                        public void SetState(bool state) {
                            spriteRenderer.color = state ? Color.white : Color.black;
                        }                                            
                    
                

This clean separation allows for easy stylistic updates (e.g., color gradients for aging cells).

Additionally, the GameOfLife script updates a UI text element in real time:

                    
                        Generation: 
                        Population:                                                                      
                    
                

This turns the simulation into an educational tool by displaying meaningful metrics about system evolution and entropy over time.

3.6 User Interaction

Although primarily automatic, the simulation allows limited input for control:

  • Press R – Randomizes and restarts the grid with a new seed.
  • Start/Pause(planned in GameUI) – Toggles simulation activity.

This minimal interactivity supports experimentation while preserving the integrity of the automated evolution process.

4. Technical Architecture

Component Role Key Features
Cell.cs Visual unit class Sprite-based rendering, binary alive/dead state
GameOfLife.cs Simulation core Grid management, rule computation, pooling, statistics
GameUI.cs User interface prototype Start/pause toggle (future feature), info display
UnityEngine & UI Framework Physics-less rendering, performance control, camera scaling

The architecture is designed to be data-driven — simulation logic depends only on grid data, not object hierarchy, ensuring scalability and maintainability.

5. Challenges and Solutions

5.1 Performance Bottlenecks

Early versions instantiated thousands of cells directly in the scene, resulting in stutter and frame drops.

Solution: Introduced an object pooling system that recycles cells efficiently.

5.2 Edge Handling

Out-of-bounds array access occurred during neighbor checking near grid edges.

Solution: Implemented boundary checks before counting neighbors:

                    
                        if (nx >= 0 && ny >= 0 && nx < width && ny < height)                                          
                    
                

5.3 Synchronization Artifacts

Updating the grid in place led to “ripple errors” where changes propagated incorrectly within the same frame.

Solution: Used a double-buffer system (grid and nextGen) to separate current and next states before applying updates.

5.4 Restart Consistency

Restarting the simulation left old cells active on screen.

Solution: Added a RestartGame() method that cleanly resets the grid, pool, and counters before reinitializing.

6. Testing and Iteration

Testing involved adjusting:

  • Grid size (width, height) for scalability.
  • Pool size (poolSize) for memory efficiency.
  • Time step (TimeInterval) to balance speed and visibility.

Each test iteration measured frame rate consistency and verified correct application of Conway’s rules (e.g., still lifes, oscillators, gliders).

Iterations also validated the population counter, confirming accurate tracking of live cell counts across generations.

7. Final Outcome

The finished simulation successfully:

  • Runs efficiently with over 20,000 active cells on screen.
  • Displays smooth evolution cycles without frame lag.
  • Provides informative metrics (generation, population).
  • Demonstrates modular, maintainable Unity C# code.
  • Creates a visually engaging and educational tool for procedural systems.

The final product effectively bridges mathematical logic and visual interaction, highlighting the elegance of emergent complexity from simple rules.

8. Insights and Lessons Learned

Key takeaways from the development process include:

  • Optimization is Crucial in Simulation Design: Even simple logic becomes performance-heavy at large scales; preemptive pooling prevents later performance crises.
  • Data Separation Simplifies Debugging: Maintaining visual and logical states independently makes iteration faster and less error-prone.
  • Readable Architecture Encourages Extensibility: Modular code allows easy adaptation for other cellular automata like Langton’s Ant or Wireworld.
  • Emergence as a Design Principle: Simple, deterministic rules can produce unexpectedly rich and organic patterns — a powerful lesson in both art and computation.

9. Future Improvements

Planned or potential enhancements include:

  • UI Expansion: Add sliders to adjust speed, density, and grid size in real time.
  • User Drawing Mode Allow players to paint live/dead cells interactively.
  • Pattern Library: Load predefined structures (e.g., gliders, pulsars, ships)
  • Color Mapping: Represent cell age or activity frequency through gradients.
  • GPU Optimization: Offload computations to shaders for real-time high-resolution grids.

These extensions would transform the project into a fully interactive laboratory for procedural simulation and emergent behavior study.

10. Conclusion

Conway’s Game of Life – Cellular Automaton serves as both a technical showcase and a conceptual exploration.

It demonstrates how a timeless algorithm can be translated into a modern, optimized, and interactive experience through Unity.

Through the development of this project, I strengthened my understanding of:

  • Efficient memory and object management.
  • Algorithmic simulation of autonomous systems.
  • The interplay between mathematics, visualization, and software design.

This project stands as a compelling example of my ability to design, optimize, and communicate complex systems with clarity and precision — an essential skillset in both game development and interactive simulation design.